﻿using System.Collections.Generic;
using DataScripter.Database;
using DataScripter.Scripting;
using DataScripter.Scripting.InputSources;
using DataScripter.Scripting.Output;
using DataScripter.Scripting.Output.Sql.SqlServer;
using DataScripter.Scripting.OutputDestinations;
using DataScripter.Scripting.ScriptDefinitions;
using DataScripter.UnitTests.Util;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace DataScripter.UnitTests.EngineTests.ScriptOrder
{
    [TestClass]
    public class RequestsAbcWithForeignKeysAbAndCbAndFiltersBaAndCb
    {
        private readonly IScriptDefinition _scriptDefinition;
        private readonly SqlServerScriptOptions _options;
        private readonly IOutputProducer _producer;

        public RequestsAbcWithForeignKeysAbAndCbAndFiltersBaAndCb()
        {
            const string tableNameA = "a";
            const string tableNameB = "b";
            const string tableNameC = "c";

            Mock<ITableStructure> aTableStructureMock = new Mock<ITableStructure>();
            IForeignKey keyAb = new ForeignKeyInfo("a_b_FK", "dbo", tableNameA, "ab", "dbo", tableNameB, "ba");
            aTableStructureMock.Setup(ts => ts.ForeignKeys).Returns(new List<IForeignKey> { keyAb });

            Mock<ITableStructure> bTableStructureMock = new Mock<ITableStructure>();
            bTableStructureMock.Setup(s => s.ForeignKeys).Returns(new List<IForeignKey>());

            Mock<ITableStructure> cTableStructureMock = new Mock<ITableStructure>();
            IForeignKey keyCb = new ForeignKeyInfo("c_b_FK", "dbo", tableNameC, "cb", "dbo", tableNameB, "bc");
            cTableStructureMock.Setup(ts => ts.ForeignKeys).Returns(new List<IForeignKey> { keyCb });

            Mock<IDataProducer> dataProducerMock = new Mock<IDataProducer>();
            _producer = new OutputProducerRecorder();

            Mock<IDatabaseStructure> structureMock = new Mock<IDatabaseStructure>();
            structureMock.Setup(s => s.GetTable(tableNameA)).Returns(aTableStructureMock.Object);
            structureMock.Setup(s => s.GetTable(tableNameB)).Returns(bTableStructureMock.Object);
            structureMock.Setup(s => s.GetTable(tableNameC)).Returns(cTableStructureMock.Object);

            Engine engine = new Engine();

            IInputSource inputSource = new SqlServerInputSource("", engine);
            engine.RegisterType(inputSource);
            IOutputDestination outputDestination = new FileOutputDestination("", engine);
            engine.RegisterType(outputDestination);

            engine.RegisterType(structureMock.Object);
            inputSource.RegisterType(dataProducerMock.Object);
            outputDestination.RegisterType(_producer);

            _scriptDefinition = new ScriptDefinition("", engine);
            engine.RegisterType(_scriptDefinition);


            _scriptDefinition.RequestScript("a");
            _scriptDefinition.RequestScript("b").FilterByForeignKey(keyAb);
            _scriptDefinition.RequestScript("c").FilterByForeignKey(keyCb);

            _options = new SqlServerScriptOptions(SqlScriptType.Insert)
                           {
                               ScriptOutputType = ScriptOutputType.Memory
                           };

            engine.Script(_options);
        }

        [TestMethod]
        public void ShouldBeInOrderAbcDef()
        {
            ((OutputProducerRecorder)_producer).AssertOrder("b", "a", "c");
        }
    }
}
